package com.finance.framework.file;

import com.aliyun.oss.ClientException;
import com.aliyun.oss.OSSClient;
import com.aliyun.oss.OSSException;
import com.aliyun.oss.model.*;
import com.finance.base.constant.BaseConstants;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.ArrayList;
import java.util.List;

/**
 * Created by gyw on 2017/4/18.
 */
public class FileUtils {
    protected final static Logger logger = LoggerFactory.getLogger(FileUtils.class);

    public static final String OSS_FILE_SEPARATOR ="/";


    private static final String ENDPOINT = BaseConstants.getOssProperties(BaseConstants.OSS_ENDPOINT);//ENDPOINT

    private static final String ACCESS_ID = BaseConstants.getOssProperties(BaseConstants.OSS_ACCESS_ID);//ACCESS_ID

    private static final String ACCESS_KEY = BaseConstants.getOssProperties(BaseConstants.OSS_ACCESS_KEY);//ACCESS_KEY

    private static final String BUCKET_NAME = BaseConstants.getOssProperties(BaseConstants.OSS_BUCKET_NAME);//BUKET_NAME

    private static OSSClient client = null;

    /**
     * 初始化OSSClient对象
     */
    static {
        client = new OSSClient(ENDPOINT,ACCESS_ID, ACCESS_KEY);
    }

    /**
     *
     * @param key  服务器的文件名称
     * @param file 文件
     * @param serviceName 服务器名称
     * @return
     */
    public static String ossPutObject(String key, File file, String serviceName) {
        ObjectMetadata objectMeta = new ObjectMetadata();
        objectMeta.setContentLength(file.length());
        // 在metadata中标记文件类型
        if (file.getName().endsWith("xml")) {
            objectMeta.setContentType("text/xml");
        }
        else if (file.getName().endsWith("jpg")) {
            objectMeta.setContentType("image/jpeg");
        }
        else if (file.getName().endsWith("png")) {
            objectMeta.setContentType("image/png");
        }
        else if (file.getName().endsWith("xlsx")) {
            objectMeta.setContentType("text/xlsx");
        }
        InputStream input;
        try {
            input = new FileInputStream(file);
            client.putObject(BUCKET_NAME, serviceName + "/" + key, input, objectMeta);
        } catch (FileNotFoundException e) {
            logger.error(e.getMessage(),e);
        }
        return "http://" + BUCKET_NAME + ".oss-cn-hangzhou.aliyuncs.com/" + serviceName + "/" + key;
    }

    /**
     * 获取bucket中所用key
     * @return
     */
    public static List getKeyByBucket(){
        ObjectListing listing = client.listObjects(BUCKET_NAME);
        List list = new ArrayList();
        for (OSSObjectSummary objectSummary : listing.getObjectSummaries()) {
            System.out.println(objectSummary.getKey());
            list.add(objectSummary.getKey());
        }
        return list;
    }

    /**
     * 上传文件到OSS
     * @return
     */
    public static String ossUpload(String key,String filePath,String fileName)throws OSSException, ClientException, FileNotFoundException{
        String keys="";
        File file = new File(filePath);
        ObjectMetadata objectMeta = new ObjectMetadata();
        objectMeta.setContentLength(file.length());
        // 在metadata中标记文件类型
        if (fileName.endsWith("xml")) {
            objectMeta.setContentType("text/xml");
        }
        else if (fileName.endsWith("jpg")) {
            objectMeta.setContentType("image/jpeg");
        }
        else if (fileName.endsWith("png")) {
            objectMeta.setContentType("image/png");
        }
        InputStream input = new FileInputStream(file);
        if(!"".equals(key)){
            keys = key + "/" + fileName;
        }else{
            keys = fileName;
        }
        client.putObject(BUCKET_NAME, keys, input, objectMeta);
        return keys;
    }

    /**
     * 删除文件
     * @param bucketName
     * @param key
     */
    public static void deleteOssObject(String bucketName, String key){
        // 创建OSSClient实例
        OSSClient ossClient = new OSSClient(ENDPOINT, ACCESS_ID, ACCESS_KEY);
        // 删除Object
        ossClient.deleteObject(bucketName,key);
        // 关闭client
        ossClient.shutdown();
    }

    /**
     * 批量删除文件
     * @param bucketName
     * @param keys
     * @return
     */
    public static List<String> batchDeleteOssObject(String bucketName, List<String> keys){
        // 创建OSSClient实例
        OSSClient ossClient = new OSSClient(ENDPOINT, ACCESS_ID, ACCESS_KEY);
        // 删除Objects
        keys.add("key0");
        keys.add("key1");
        keys.add("key2");
        DeleteObjectsResult deleteObjectsResult = ossClient.deleteObjects(new DeleteObjectsRequest(bucketName).withKeys(keys));
        List<String> deletedObjects = deleteObjectsResult.getDeletedObjects();
        // 关闭client
        ossClient.shutdown();
        return deletedObjects;
    }

    /**
     * 普通方式文件上传
     * @param url
     * @param file
     * @return
     */
    /*public static String fileload(String url, File file) {
        String body = "{}";

        if (url == null || url.equals("")) {
            return "参数不合法";
        }
        if (!file.exists()) {
            return "要上传的文件名不存在";
        }

        PostMethod postMethod = new PostMethod(url);

        try {
            // FilePart：用来上传文件的类,file即要上传的文件
            FilePart fp = new FilePart("file", file);
            Part[] parts = { fp };

            // 对于MIME类型的请求，httpclient建议全用MulitPartRequestEntity进行包装
            MultipartRequestEntity mre = new MultipartRequestEntity(parts, postMethod.getParams());
            postMethod.setRequestEntity(mre);

            HttpClient client = new HttpClient();
            // 由于要上传的文件可能比较大 , 因此在此设置最大的连接超时时间
            client.getHttpConnectionManager().getParams() .setConnectionTimeout(50000);

            int status = client.executeMethod(postMethod);
            if (status == HttpStatus.SC_OK) {
                InputStream inputStream = postMethod.getResponseBodyAsStream();
                BufferedReader br = new BufferedReader(new InputStreamReader(inputStream,"UTF-8"));
                StringBuffer stringBuffer = new StringBuffer();
                String str = "";
                while ((str = br.readLine()) != null) {
                    stringBuffer.append(str);
                }
                body = stringBuffer.toString();
                br.close();
            } else {
                body = "fail";
            }
        } catch (Exception e) {
            logger.warn("上传文件异常", e);
        } finally {
            // 释放连接
            postMethod.releaseConnection();
        }
        return body;
    }*/

    /**
     * 普通方式文件下载
     * @param path
     * @param response
     * @return
     */
    public static HttpServletResponse download(String path, HttpServletResponse response) {
        try {
            // path是指欲下载的文件的路径。
            File file = new File(path);
            // 取得文件名。
            String filename = file.getName();
            // 取得文件的后缀名。
            String ext = filename.substring(filename.lastIndexOf(".") + 1).toUpperCase();

            // 以流的形式下载文件。
            InputStream fis = new BufferedInputStream(new FileInputStream(path));
            byte[] buffer = new byte[fis.available()];
            fis.read(buffer);
            fis.close();
            // 清空response
            response.reset();
            // 设置response的Header
            response.addHeader("Content-Disposition", "attachment;filename=" + new String(filename.getBytes("UTF-8"),"UTF-8"));
            response.addHeader("Content-Length", "" + file.length());
            OutputStream toClient = new BufferedOutputStream(response.getOutputStream());
            response.setContentType("application/octet-stream");
            toClient.write(buffer);
            toClient.flush();
            toClient.close();
        } catch (IOException ex) {
            ex.printStackTrace();
        }
        return response;
    }

    /**
     * 创建Bucket
     * @param client  OSSClient对象
     * @param bucketName  BUCKET名
     * @throws OSSException
     * @throws ClientException
     */
    public static void ensureBucket(OSSClient client, String bucketName)throws OSSException, ClientException {
        try{
            client.createBucket(bucketName);
        }catch(Exception e){
             logger.error(e.getMessage(),e);
        }
    }

    /**
     * 把Bucket设置成所有人可读
     * @param client  OSSClient对象
     * @param bucketName  Bucket名
     * @throws OSSException
     * @throws ClientException
     */
    public static void setBucketPublicReadable(OSSClient client, String bucketName)throws OSSException, ClientException{
        //创建bucket
        client.createBucket(bucketName);
        //设置bucket的访问权限， public-read-write权限
        client.setBucketAcl(bucketName, CannedAccessControlList.PublicRead);
    }

    /**
     *  下载文件
     *
     * @param client  OSSClient对象
     * @param bucketName  Bucket名
     * @param Objectkey  上传到OSS起的名
     * @param downloadFilePath 文件下载到本地保存的路径(包括名称)
     * @throws OSSException
     * @throws ClientException
     */
    public static void downloadFile(OSSClient client, String bucketName, String Objectkey, String downloadFilePath)
            throws OSSException, ClientException {
        client.getObject(new GetObjectRequest(bucketName, Objectkey),new File(downloadFilePath));
    }


    /**
     *
     * @author ljg
     * @param dirName 目录名
     * @param fileName 文件名 包含后缀
     * @param in  流文件
     * @return key 根据key 获取文件
     * */
    public static String uploadFile(String dirName,String fileName,InputStream in){
        return uploadFile(null,dirName,fileName,in);
    }

    /**
     * @author ljg
     * @param bucketName bucket名字 如果空 默认
     * @param dirName 目录名
     * @param fileName 文件名 包含后缀
     * @param in  流文件
     * @return key 根据key 获取文件
     * */
    public static String uploadFile(String bucketName,String dirName,String fileName,InputStream in){
        if(StringUtils.isNotEmpty(dirName)){
            dirName=dirName.lastIndexOf(OSS_FILE_SEPARATOR)==(dirName.length()-1)?dirName:(dirName+OSS_FILE_SEPARATOR);
            fileName=dirName+fileName;
        }
        if(StringUtils.isEmpty(bucketName)){
            bucketName=BUCKET_NAME;
        }
        client.putObject(bucketName, fileName, in);
        return fileName;
    }

    /**
     * @author ljg
     * @param dirName 目录名
     * @param fileName 文件名 包含后缀
     * @param file  上传的文件
     * @return key 根据key 获取文件
     * */
    public static String uploadFile(String dirName,String fileName,File file) throws FileNotFoundException {
        return uploadFile(dirName,fileName,new FileInputStream(file));
    }

    /**
     * @author ljg
     * @param filePath 下载的文件名 全路径
     * */
    public static void delFile(String filePath) throws FileNotFoundException {
        client.deleteObject(BUCKET_NAME,filePath);
    }

    /**
     * @author ljg
     * @param filePath 下载的文件名 全路径
     * @param response 响应对象
     * */
    public static void downFile(String filePath,HttpServletResponse response) {
        String fileName=filePath.substring(filePath.lastIndexOf(OSS_FILE_SEPARATOR)+1,filePath.length());
        response.setHeader("content-disposition", "attachment;filename="+fileName);
        OutputStream out= null;
        InputStream in=null;
        try {
            OSSObject ossObject = client.getObject(BUCKET_NAME, filePath);

            out = response.getOutputStream();
            in=ossObject.getObjectContent();
            int i=in.read();
            while (i!=-1){
                out.write(i);
                i=in.read();
            }
            out.flush();
        } catch (IOException e) {
            logger.error(e.getMessage(),e);
        }finally {
            if(in!=null){
                try {
                    in.close();
                } catch (IOException e) {
                    logger.error(e.getMessage(),e);
                }
            }
            if(out!=null){
                try {
                    out.close();
                } catch (IOException e) {
                    logger.error(e.getMessage(),e);
                }
            }
        }
    }

    public static boolean exist(String buckName,String key){
        try {
            ObjectMetadata objectMetadata = client.getObjectMetadata(buckName, key);
            return objectMetadata != null;
        }catch (Exception e){
            return  false;
        }
    }

}

